"""
智面 API 使用示例

这个脚本展示了如何使用 Python 与智面 API 进行交互。
所有 AI 生成接口都使用流式响应（SSE）。

## 核心特性

### 1. 简历上传功能
- 支持两种方式：直接传递文本（cv_text）或上传文件（cv_file_path）
- 支持的文件格式：PDF, DOCX, DOC, TXT, MD, RTF
- 文件大小限制：10MB
- 使用 unstructured[all-docs] 库自动解析简历内容

### 2. 结构化面试流程（被动 RAG）
面试官会按照以下 5 个阶段循序渐进地进行面试：
1. **开场与破冰**（1-2 轮对话）- 自我介绍、说明流程
2. **基础知识考察**（3-5 个问题）- 考察基础理论知识
3. **项目经历深入**（4-6 个问题）- 深入了解项目经验
4. **技术深度与难题**（3-4 个问题）- 考察技术深度
5. **综合评估与收尾**（1-2 个问题）- 候选人提问、结束

**核心特点**：
- 每次只问一个问题，避免候选人困惑
- 面试结束时会输出 `[面试结束]` 标记
- 每次用户回答都会自动触发 RAG 检索，增强提问专业度

### 3. 被动 RAG（Retrieval-Augmented Generation）
- 系统使用用户的最新消息作为查询进行知识检索
- 通过 white_paper_tag 过滤，只检索当前岗位的知识库
- CV 和 JD 作为完整上下文，始终提供给 LLM
- RAG 检索结果用于增强面试官提问的专业性和针对性
"""

import requests
import json
from typing import Optional


class ZhimianClient:
    """智面 API 客户端"""

    def __init__(self, base_url: str = "http://localhost:8000"):
        self.base_url = base_url
        self.token: Optional[str] = None

    def register(self, username: str, email: str, password: str) -> dict:
        """用户注册"""
        response = requests.post(
            f"{self.base_url}/api/auth/register",
            json={"username": username, "email": email, "password": password},
        )
        response.raise_for_status()
        return response.json()

    def login(self, username: str, password: str) -> str:
        """用户登录，返回 token"""
        response = requests.post(
            f"{self.base_url}/api/auth/token",
            data={"username": username, "password": password},
        )
        response.raise_for_status()
        data = response.json()
        self.token = data["access_token"]
        return self.token

    def get_positions(self) -> list:
        """获取岗位列表"""
        response = requests.get(
            f"{self.base_url}/api/positions/",
            headers={"Authorization": f"Bearer {self.token}"},
        )
        response.raise_for_status()
        return response.json()

    def start_interview(
        self, position_id: str, cv_text: str = None, cv_file_path: str = None
    ) -> dict:
        """
        开始面试

        Args:
            position_id: 岗位 ID
            cv_text: 简历文本（与 cv_file_path 二选一）
            cv_file_path: 简历文件路径（与 cv_text 二选一）

        Returns:
            dict: 面试会话信息
        """
        if cv_file_path:
            # 使用文件上传方式
            import os

            # 获取文件名
            filename = os.path.basename(cv_file_path)

            # 根据文件扩展名确定 content_type
            content_type_map = {
                ".pdf": "application/pdf",
                ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".doc": "application/msword",
                ".txt": "text/plain",
                ".md": "text/markdown",
                ".rtf": "application/rtf",
            }

            ext = os.path.splitext(filename)[1].lower()
            content_type = content_type_map.get(ext, "application/octet-stream")

            with open(cv_file_path, "rb") as f:
                # 正确指定文件名和 content_type
                files = {"cv_file": (filename, f, content_type)}
                data = {"position_id": position_id}
                response = requests.post(
                    f"{self.base_url}/api/interview/start",
                    headers={"Authorization": f"Bearer {self.token}"},
                    files=files,
                    data=data,
                )
                # 在文件关闭前检查响应
                try:
                    response.raise_for_status()
                    return response.json()
                except requests.exceptions.HTTPError:
                    # 打印详细错误信息
                    print(f"错误详情: {response.text}")
                    raise
        else:
            # 使用文本方式
            data = {"position_id": position_id, "cv_text": cv_text}
            response = requests.post(
                f"{self.base_url}/api/interview/start",
                headers={"Authorization": f"Bearer {self.token}"},
                data=data,
            )
            response.raise_for_status()
            return response.json()

    def chat(self, session_id: str, message: str, stream: bool = True) -> dict:
        """
        发送消息（流式 + 结构化面试流程）

        **结构化面试流程：**
        面试官会按照以下 5 个阶段进行面试，每次只问一个问题：
        1. 开场与破冰（1-2 轮对话）
        2. 基础知识考察（3-5 个问题）
        3. 项目经历深入（4-6 个问题）
        4. 技术深度与难题（3-4 个问题）
        5. 综合评估与收尾（1-2 个问题）

        当面试结束时，AI 会在回复中包含 [面试结束] 标记。

        Args:
            session_id: 会话 ID
            message: 用户消息
            stream: 是否启用流式输出（默认 True）

        Returns:
            dict: {
                'response': str - 完整的 AI 回复,
                'interview_finished': bool - 面试是否结束
            }
        """
        response = requests.post(
            f"{self.base_url}/api/interview/chat",
            headers={"Authorization": f"Bearer {self.token}"},
            json={"session_id": session_id, "message": message},
            stream=True,  # 启用流式响应
        )
        response.raise_for_status()

        full_response = ""
        interview_finished = False

        if stream:
            # 流式输出
            print("AI: ", end="", flush=True)

        # 逐行读取 SSE 响应
        for line in response.iter_lines():
            if line:
                line_text = line.decode("utf-8")

                if line_text.startswith("data: "):
                    json_str = line_text[6:]  # 去掉 "data: " 前缀

                    try:
                        data = json.loads(json_str)

                        if "chunk" in data:
                            chunk = data["chunk"]
                            full_response += chunk
                            if stream:
                                print(chunk, end="", flush=True)

                        elif "done" in data and data["done"]:
                            # 检查是否包含面试结束标记
                            interview_finished = data.get("interview_finished", False)
                            if stream:
                                print()  # 换行
                                if interview_finished:
                                    print("\n" + "=" * 50)
                                    print(
                                        "🎉 面试已结束！您可以调用 analyze() 生成面试分析报告。"
                                    )
                                    print("=" * 50 + "\n")
                            break

                        elif "error" in data:
                            raise Exception(f"API 错误: {data['error']}")

                    except json.JSONDecodeError:
                        pass

        return {"response": full_response, "interview_finished": interview_finished}

    def analyze(self, session_id: str, stream: bool = True) -> str:
        """
        生成分析报告（流式）

        Args:
            session_id: 会话 ID
            stream: 是否启用流式输出（默认 True）

        Returns:
            str: 完整的分析报告
        """
        response = requests.post(
            f"{self.base_url}/api/interview/analyze",
            headers={"Authorization": f"Bearer {self.token}"},
            json={"session_id": session_id},
            stream=True,  # 启用流式响应
        )
        response.raise_for_status()

        full_report = ""

        if stream:
            print("\n正在生成分析报告...\n")
            print("-" * 60)

        # 逐行读取 SSE 响应
        for line in response.iter_lines():
            if line:
                line_text = line.decode("utf-8")

                if line_text.startswith("data: "):
                    json_str = line_text[6:]

                    try:
                        data = json.loads(json_str)

                        if "chunk" in data:
                            chunk = data["chunk"]
                            full_report += chunk
                            if stream:
                                print(chunk, end="", flush=True)

                        elif "done" in data and data["done"]:
                            if stream:
                                print("\n" + "-" * 60)
                            break

                        elif "error" in data:
                            raise Exception(f"API 错误: {data['error']}")

                    except json.JSONDecodeError:
                        pass

        return full_report

    def get_messages(self, session_id: str) -> list:
        """获取会话消息"""
        response = requests.get(
            f"{self.base_url}/api/interview/sessions/{session_id}/messages",
            headers={"Authorization": f"Bearer {self.token}"},
        )
        response.raise_for_status()
        return response.json()


def main():
    """示例：完整的面试流程"""

    # 初始化客户端
    client = ZhimianClient(base_url="http://43.142.2.245:8000")

    print("=" * 60)
    print("智面 API 使用示例")
    print("=" * 60)

    # 1. 注册用户
    print("\n1. 注册用户...")
    try:
        user = client.register(
            username="test", email="test@example.com", password="password123"
        )
        print(f"✅ 注册成功: {user['username']}")
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 400:
            print("⚠️  用户已存在，跳过注册")
        else:
            raise

    # 2. 登录
    print("\n2. 用户登录...")
    client.login("test", "password123")
    print("✅ 登录成功")

    # 3. 获取岗位列表
    print("\n3. 获取岗位列表...")
    positions = client.get_positions()
    if not positions:
        print("❌ 没有可用的岗位，请先运行: python scripts/create_sample_data.py")
        return

    print(f"✅ 找到 {len(positions)} 个岗位:")
    for i, pos in enumerate(positions, 1):
        print(f"   {i}. {pos['title']} ({pos['white_paper_tag']})")

    # 选择第一个岗位
    for position in positions:
        if position["title"] == "Python 后端工程师":
            selected_position = position
            break
    print(f"\n📌 选择岗位: {selected_position['title']}")

    # 4. 开始面试（支持两种方式：文本或文件上传）
    print("\n4. 开始面试...")
    print("   支持两种方式提供简历：")
    print("   方式1: 直接传递文本（cv_text）")
    print("   方式2: 上传文件（cv_file_path）- 支持 PDF, DOCX, DOC, TXT 等格式")

    # 方式1: 使用文本方式（取消注释以使用）
    # cv_text = """
    # 姓名：张三
    # 教育背景：
    # - 本科，计算机科学与技术，2018-2022
    #
    # 工作经历：
    # - Python 后端开发工程师，某科技公司，2022-至今
    #   - 使用 FastAPI 开发 RESTful API
    #   - 使用 PostgreSQL 设计和优化数据库
    #   - 参与微服务架构设计和实现
    #
    # 技能：
    # - 熟练掌握 Python、FastAPI、Django
    # - 熟悉 PostgreSQL、Redis、MongoDB
    # - 了解 Docker、Kubernetes
    # - 熟悉 Git、CI/CD
    # """
    #
    # session = client.start_interview(
    #     position_id=selected_position["position_id"], cv_text=cv_text
    # )

    # 方式2: 使用文件上传方式（默认示例）
    session = client.start_interview(
        position_id=selected_position["position_id"],
        cv_file_path="data/张艺鹏.pdf",
    )

    session_id = session["session_id"]
    print(f"✅ 面试会话创建成功: {session_id}")

    # 5. 进行面试对话（流式 + 结构化流程）
    print("\n5. 开始面试对话（流式输出 + 结构化面试流程）...")
    print("\n📋 面试流程说明：")
    print("   面试官会按照以下阶段循序渐进地进行面试：")
    print("   1. 开场与破冰（1-2 轮对话）")
    print("   2. 基础知识考察（3-5 个问题）")
    print("   3. 项目经历深入（4-6 个问题）")
    print("   4. 技术深度与难题（3-4 个问题）")
    print("   5. 综合评估与收尾（1-2 个问题）")
    print("\n⚠️  面试官每次只问一个问题，避免混淆")
    print("=" * 60)

    # 开始面试对话循环
    # 第一轮：开场
    user_message = "您好，我准备好了，可以开始了。"
    print(f"\n候选人: {user_message}\n")
    result = client.chat(session_id, user_message, stream=True)

    # 继续对话，直到面试结束
    # 这里提供几个示例回答
    sample_responses = [
        "我叫张三，毕业于XX大学计算机专业，有2年的Python后端开发经验。",
        "我主要使用FastAPI框架开发过电商系统的后端API，包括用户管理、订单处理、支付集成等模块。",
        "在这个项目中，我负责设计API架构、实现业务逻辑和数据库设计。团队有5个人，我是后端负责人。",
        "我使用了PostgreSQL作为主数据库，Redis做缓存，还用了Celery处理异步任务。",
        "遇到的最大挑战是并发性能问题。高峰期时响应时间很长，我通过数据库索引优化、添加Redis缓存和使用连接池，将响应时间从2秒优化到了200ms。",
        "对于异步任务，我用Celery配合Redis做消息队列，处理订单确认、邮件发送等耗时操作。",
        "在架构设计上，我倾向于使用领域驱动设计（DDD），将业务逻辑清晰地分层。",
        "我希望能在一个技术氛围好的团队，有机会学习更多的架构设计和大规模系统优化经验。",
        "我想了解一下团队的技术栈和开发流程是怎样的？",
        "没有了，谢谢。",
    ]

    # 模拟面试对话
    for i, response in enumerate(sample_responses):
        if result.get("interview_finished"):
            break

        print(f"\n候选人: {response}\n")
        result = client.chat(session_id, response, stream=True)

    print("\n" + "=" * 60)

    # 6. 生成分析报告（流式）
    if result.get("interview_finished"):
        print("\n6. 生成面试分析报告（流式输出）...")
        print("-" * 60)
        # 流式生成并输出分析报告
        client.analyze(session_id, stream=True)
    else:
        print("\n⚠️  面试尚未完成，可以继续对话或手动调用 analyze() 生成报告")

    print("\n" + "=" * 60)
    print("✅ 分析报告生成完成")
    print("=" * 60)

    # 7. 查看完整对话记录
    print("\n7. 查看完整对话记录...")
    messages = client.get_messages(session_id)
    print(f"\n共有 {len(messages)} 条消息:")
    for msg in messages:
        role_name = "候选人" if msg["role"] == "human" else "面试官"
        print(f"\n{role_name}: {msg['content'][:100]}...")

    print("\n" + "=" * 60)
    print("✅ 示例完成！")
    print("=" * 60)


if __name__ == "__main__":
    # 运行完整的面试流程示例（使用文本方式）
    main()

    # 如需测试文件上传功能，请取消下面的注释
    # print("\n\n")
    # example_upload_resume_file()
